/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.command;

import static com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil.getOperands;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.InteractionOperand;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.sedi.edit.CFEditPart;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;

/**
 * TODO Document
 * 
 * @author frankd@ifi.uio.no
 */
public class OperandUtils {

    private OperandUtils() {
        // private to disallow instantiation
    }

    /**
     * Returns the bounds of the InteractionOperand (that the command operates on). The
     * bounds are returned in absolute coordinates.
     */
    @SuppressWarnings("unchecked")
    public static Rectangle getOperandBounds(final Diagram diagram,
            final InteractionOperand operand, final EditPart anyEditPart) {
        final CombinedFragment cfragment = (CombinedFragment) operand.getOwner();
        ArrayList<GraphNode> listCFrag =
                LookForElement.lookForGraphElementWODiagram(cfragment, diagram,
                        new ArrayList<GraphNode>(1));
        final GraphNode cfragmentView = listCFrag.get(0);

        final List<InteractionOperand> operands = getOperands(cfragment);
        int operandIndex = operands.indexOf(operand);

        // CF bounds
        Rectangle cfragmentBounds =
                new Rectangle(cfragmentView.getPosition().getCopy(), cfragmentView.getSize()
                        .getCopy());
        // GraphicalEditPart cfragmentEP =
        // (GraphicalEditPart) anyEditPart.getViewer().getEditPartRegistry()
        // .get(cfragmentView);
        // cfragmentEP.getFigure().translateToAbsolute(cfragmentBounds);

        // Operand coords
        final int top = getSeparatorCoordinate(diagram, operand, anyEditPart);

        operandIndex++;
        final int bottom =
                (operandIndex < operands.size()) ? getSeparatorCoordinate(diagram, operands
                        .get(operandIndex), anyEditPart) : cfragmentBounds.getBottom().y;

        return new Rectangle(cfragmentBounds.x, top, cfragmentBounds.width, bottom - top);
    }

    /**
     * Returns the top y-coordinate (in absolute coords) of the separator for the given
     * operand.
     */
    @SuppressWarnings("unchecked")
    public static int getSeparatorCoordinate(final Diagram diagram,
            final InteractionOperand operand, final EditPart anyEditPart) {

        final CombinedFragment cfragment = (CombinedFragment) operand.getOwner();
        final int index = cfragment.getOperands().indexOf(operand);
        if (index == 0) {
            List<GraphNode> listCFrag =
                    LookForElement.lookForGraphElementWODiagram(cfragment, diagram,
                            new ArrayList<GraphNode>(1));
            GraphNode cfragmentView = listCFrag.get(0);
            Point cfLoc = cfragmentView.getPosition();
            // GraphicalEditPart cfragmentEP =
            // (GraphicalEditPart) anyEditPart.getViewer().getEditPartRegistry().get(
            // cfragmentView);
            // cfragmentEP.getFigure().translateToAbsolute(cfLoc);
            return cfLoc.y;
        } else {
            List<GraphEdge> listEdge =
                    LookForElement.lookForGraphElementWODiagram(operand, diagram,
                            new ArrayList<GraphEdge>(1));
            CFEditPart cfragmentEP =
                    (CFEditPart) anyEditPart.getViewer().getEditPartRegistry().get(
                            listEdge.get(0).getAnchorSource());
            ConnectionAnchor anchor =
                    cfragmentEP.getConnectionAnchor(ModelUtil.getSourceRef(listEdge.get(0)));
            return anchor.getLocation(null).y;
        }
    }
}
